package com.yanqu.road.server.manager.activity.biaoju;

import com.alibaba.fastjson.JSONObject;
import com.yanqu.road.dao.impl.activity.biaoju.CrossBiaoJuUserImpl;
import com.yanqu.road.dao.impl.activity.biaoju.CrossBiaoJuUserRunEscortImpl;
import com.yanqu.road.entity.activity.biaoju.*;
import com.yanqu.road.entity.activity.biaoju.config.BiaoJuDartConfig;
import com.yanqu.road.entity.log.cross.biaoju.LogBiaoJuExp;
import com.yanqu.road.logic.activity.biaoju.BiaoJuConfig;
import com.yanqu.road.pb.activity.BiaoJuProto;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.log.CrossAutoLogMgr;
import com.yanqu.road.server.manager.user.CrossUserMgr;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.GameProtocol;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import org.apache.mina.util.ConcurrentHashSet;

import java.util.*;

public class CrossBiaoJuUserInfo {
    private CrossBiaoJuUserData userData;
    private CrossBiaoJuUserRunEscortData runEscortData;
    private List<CrossBiaoJuUserRunEscortData> historyEscortList = new ArrayList<>(); //历史开启的跑镖数据

    private long rankScore;
    private long scoreChangeTime;

    public CrossBiaoJuUserInfo(CrossBiaoJuUserData userData) {
        this.userData = userData;
    }

    public CrossBiaoJuUserData getUserData() {
        return userData;
    }

    public CrossBiaoJuUserRunEscortData getRunEscortData() {
        return runEscortData;
    }

    public CrossBiaoJuUserRunEscortData getLastNotConfirmHistoryEscort() {
        for (CrossBiaoJuUserRunEscortData escortData : historyEscortList) {
            if (escortData.getFinishTime() > userData.getLastConfirmFinishTime()) {
                return escortData;
            }
        }
        return null;
    }

    public synchronized List<CrossBiaoJuUserRunEscortData> getLastNotConfirmHistoryEscortByJoin(long lastConfirmTime, long teamUserId) {
        List<CrossBiaoJuUserRunEscortData> result = new ArrayList<>();
        for (CrossBiaoJuUserRunEscortData escortData : historyEscortList) {
            if (escortData.getFinishTime() > lastConfirmTime) {
                if (escortData.getTeamUserList().stream().anyMatch(biaoJuTeamUserInfo -> biaoJuTeamUserInfo.getUserId() == teamUserId)) {
                    result.add(escortData);
                }
            }
        }
        return result;
    }

    public synchronized List<BiaoJuUserEscortInfo> getWaitTakeList() {
        return new ArrayList<>(userData.getWaitTakeList());
    }

    /**
     * 获得最近一次已完成押镖
     *
     * @return
     */
    public synchronized CrossBiaoJuUserRunEscortData getLastOneHistoryEscort() {
        if (historyEscortList.isEmpty()) {
            return null;
        }
        return historyEscortList.get(historyEscortList.size() - 1);
    }

    /**
     * 获得最近一次押镖
     *
     * @return
     */
    public synchronized CrossBiaoJuUserRunEscortData getLastOneEscort() {
        if (runEscortData != null) {
            return runEscortData;
        }

        return getLastOneHistoryEscort();
    }

    public synchronized void updateWaitTakeList(List<BiaoJuUserEscortInfo> waitTakeList) {
        this.userData.setWaitTakeList(waitTakeList);
        this.userData.setLastRefreshTime(DateHelper.getCurrentTime());
    }

    public synchronized void setRunEscortData(CrossBiaoJuUserRunEscortData runEscortData) {
        this.runEscortData = runEscortData;
    }

    public void addGuaranteeRefreshCount(int i) {
        userData.setGuaranteeAmount(userData.getGuaranteeAmount() + i);
    }

    public void resetGuaranteeRefreshCount() {
        userData.setGuaranteeAmount(0);
    }

    /**
     * 押镖完成结算
     *
     * @param config
     * @param unionInfo
     */
    public synchronized BiaoJuRunResult endRunEscort(BiaoJuConfig config, CrossBiaoJuUnionInfo unionInfo) {
        if (runEscortData == null) {
            return null;
        }

        BiaoJuRunResult biaoJuRunResult = new BiaoJuRunResult(runEscortData);

        int unionLevel = runEscortData.getUnionLevel();

        runEscortData.setFinishTime(DateHelper.getCurrentTime());

        BiaoJuDartConfig dartConfig = config.getDartConfig(runEscortData.getEscortId());

        int finishLevel = config.calcEscortFinishLevel(runEscortData);
        int moneyAdd = 0;
        int expAdd = 0;
        if (finishLevel == 1) {
            moneyAdd = dartConfig.getIncomeBountySuccess();
            expAdd = dartConfig.getIncomeScoreSuccess();
        } else if (finishLevel == 3) {
            moneyAdd = dartConfig.getIncomeBountyFail();
            expAdd = dartConfig.getIncomeScoreFail();
        } else {
            moneyAdd = dartConfig.getIncomeBountyHalf();
            expAdd = dartConfig.getIncomeScoreHalf();
        }

        //基础收益
//        押镖经验=基础收益*（本单镖头镖师等级加成）
//        押镖赏金=基础收益*（1+商会镖局等级加成+地点投资总加成 +本单镖头镖师等级加成）
        int unionLevelAddition = config.getUnionLevelAddition(unionLevel);
        int cityRankAddition = runEscortData.getCityAddition();
        int userLevelAddition = config.getTitleAddition(runEscortData.getUserLevel());

        biaoJuRunResult.setFinishLevel(finishLevel);
        biaoJuRunResult.setBaseExp(expAdd);
        biaoJuRunResult.setBaseMoney(moneyAdd);
        biaoJuRunResult.setUnionLevelAddition(unionLevelAddition);
        biaoJuRunResult.setCityRankAddition(cityRankAddition);
        biaoJuRunResult.setUserLevelAddition(userLevelAddition);
        biaoJuRunResult.setLeaderAddition(config.getLeaderRewardMulti());

        biaoJuRunResult.calcReward();

        Property reward = new Property();
        reward.addProperty(config.getExpGoodsId(), biaoJuRunResult.getJoinExpAdd());
        reward.addProperty(config.getBountyGoodsId(), biaoJuRunResult.getJoinMoneyAdd());
        runEscortData.setReward(reward.toHelperString());

        Property leaderReward = new Property();
        leaderReward.addProperty(config.getExpGoodsId(), biaoJuRunResult.getLeaderExpAdd());
        leaderReward.addProperty(config.getBountyGoodsId(), biaoJuRunResult.getLeaderMoneyAdd());
        runEscortData.setLeaderReward(leaderReward.toHelperString());

        Map<Long, Integer> battleValueMap = new HashMap<>();
        battleValueMap.put(runEscortData.getUserId(), config.getTitleConfigMap().get(runEscortData.getUserLevel()).getPower());
        for (BiaoJuTeamUserInfo biaoJuTeamUserInfo : runEscortData.getTeamUserList()) {
            battleValueMap.put(biaoJuTeamUserInfo.getUserId(), config.getTitleConfigMap().get(biaoJuTeamUserInfo.getLevel()).getPower());
        }
        Map<Integer, Integer> battleLogsMap = new HashMap<>();
        for (int i = 0; i < runEscortData.getBattleLogList().size(); i++) {
            BiaoJuEscortBattleLog battleLog = runEscortData.getBattleLogList().get(i);
            battleLogsMap.put(i + 1, battleLog.getResult());
        }

        biaoJuRunResult.setBattleValueMap(battleValueMap);
        biaoJuRunResult.setBattleLogsMap(battleLogsMap);

        addRunReward(biaoJuRunResult, config, true);

        addHistoryRunEscort(runEscortData);
        runEscortData = null;

        return biaoJuRunResult;
    }

    public synchronized void addHistoryRunEscort(CrossBiaoJuUserRunEscortData runEscortData) {
        historyEscortList.add(runEscortData);
    }

    /**
     * 作为队友获得的奖励
     *
     * @param biaoJuRunResult
     * @param config
     */
    public synchronized void addRunReward(BiaoJuRunResult biaoJuRunResult, BiaoJuConfig config, boolean isLeader) {
        long moneyAdd = 0;
        long expAdd = 0;
        if (isLeader) {//队长有额外加成
            moneyAdd = biaoJuRunResult.getLeaderMoneyAdd();
            expAdd = biaoJuRunResult.getLeaderExpAdd();

        } else {//队员 有领取次数限制
            if (userData.getDayJoinRewardNum() > config.getDayJoinRewardLimit()) {
                return;
            }
            moneyAdd = biaoJuRunResult.getJoinMoneyAdd();
            expAdd = biaoJuRunResult.getJoinExpAdd();
        }

        userData.addMoney(moneyAdd);
        userData.addExp(expAdd);

        int newLevel = config.calcTitleLevel(userData.getExp());
        userData.setLevel(newLevel);

        CrossAutoLogMgr.add(new LogBiaoJuExp(userData.getActivityId(), userData.getUnionGroup(), userData.getUserId(), expAdd, userData.getExp(), userData.getLevel(), isLeader));

        BiaoJuProto.CrossBiaoJuRunEndSyncMsg.Builder endSyncMsg = BiaoJuProto.CrossBiaoJuRunEndSyncMsg.newBuilder();
        endSyncMsg.setExpAdd(expAdd);
        endSyncMsg.setNowExp(userData.getExp());
        endSyncMsg.setNowLevel(userData.getLevel());
        endSyncMsg.setTitleAddition(biaoJuRunResult.getUserLevelAddition());
        endSyncMsg.setUnionLevelAddition(biaoJuRunResult.getUnionLevelAddition());
        endSyncMsg.setCityAddition(biaoJuRunResult.getCityRankAddition());
        endSyncMsg.setLeaderAddition(isLeader ? biaoJuRunResult.getLeaderAddition() : 0);
        endSyncMsg.setSpeedUpTime(biaoJuRunResult.getRunEscortData().getSpeedUpTime());
        endSyncMsg.setMoneyAdd(moneyAdd);
        endSyncMsg.setEscortUniqueId(biaoJuRunResult.getRunEscortData().getUniqueId());
        endSyncMsg.setEscortId(biaoJuRunResult.getRunEscortData().getEscortId());
        endSyncMsg.setMembers(JSONObject.toJSONString(biaoJuRunResult.getBattleValueMap()));
        endSyncMsg.setBattleLogs(JSONObject.toJSONString(biaoJuRunResult.getBattleLogsMap()));
        endSyncMsg.setFinishLevel(biaoJuRunResult.getFinishLevel());

        long serverIdByUserId = CrossUserMgr.getServerIdByUserId(userData.getUserId());
        MessageHelper.sendPacket(serverIdByUserId, userData.getUserId(),
                YanQuMessageUtils.buildMessage(GameProtocol.S_BIAOJU_ESCORT_END_CROSS_BACK, endSyncMsg));
    }

    public long getRankScore() {
        return rankScore;
    }

    public long getScoreChangeTime() {
        return scoreChangeTime;
    }

    public void refreshRankParam() {
        this.rankScore = userData.getExp();
        this.scoreChangeTime = userData.getExpChangeTime();
    }

    public synchronized void setRank(int rank) {
        this.userData.setRank(rank);
    }

    public void setCanBePullQuality(List<Integer> qualityList, List<Long> canBePullId, int qualitySwitch) {
        this.userData.setCanBePullQuality(new ConcurrentHashSet<>(qualityList));
        this.userData.setCanPullId(new ConcurrentHashSet<>(canBePullId));
        this.userData.setSettingSwitch(qualitySwitch);
    }

    public synchronized List<Integer> getCanBePullQuality() {
        return new ArrayList<>(userData.getCanBePullQuality());
    }

    public boolean checkCanBePull(int gear, long userId) {
        if (!this.userData.getCanBePullQuality().contains(gear)) { //先判断品质是否满足
            return false;
        }
        if (userData.getSettingSwitch() == 1) {
            return true;
        }
        return this.userData.getCanPullId().contains(userId);
    }

    public synchronized boolean checkDayJoinNumLimit(int dayJoinLimit) {
        if (userData.getDayJoinNum() >= dayJoinLimit) {
            return false;
        }

        return true;
    }

    public synchronized boolean checkDayJoinNumLimitAndAdd(int dayJoinLimit) {
        if (userData.getDayJoinNum() >= dayJoinLimit) {
            return false;
        }

        addDayJoinNum();
        return true;
    }

    public synchronized void addDayJoinNum() {
        userData.setDayJoinNum(userData.getDayJoinNum() + 1);
        userData.setDayJoinRewardNum(userData.getDayJoinRewardNum() + 1);
    }

    public synchronized void decDayJoinNum() {
        userData.setDayJoinNum(userData.getDayJoinNum() - 1);
        userData.setDayJoinRewardNum(userData.getDayJoinRewardNum() - 1);
    }

    public synchronized void setDayJoinNum(int dayJoinNum) {
        userData.setDayJoinNum(dayJoinNum);
    }

    public synchronized void dayReset() {
        if (!DateHelper.isSameDay(userData.getLastRefreshTime() / 1000, DateHelper.getCurrentTime() / 1000)) {
            userData.setDayJoinNum(0);
            userData.setDayJoinRewardNum(0);
            userData.setDayUnionExpAdd(0);
            userData.setLastRefreshTime(DateHelper.getCurrentTime());
        }
    }

    public void save() {
        if (userData.isInsertOption()) {
            new CrossBiaoJuUserImpl().add(userData);
        } else if (userData.isUpdateOption()) {
            new CrossBiaoJuUserImpl().update(userData);
        }

        if (runEscortData != null) {
            if (runEscortData.isInsertOption()) {
                new CrossBiaoJuUserRunEscortImpl().add(runEscortData);
            } else if (runEscortData.isUpdateOption()) {
                new CrossBiaoJuUserRunEscortImpl().update(runEscortData);
            }
        }

        for (CrossBiaoJuUserRunEscortData userRunEscortData : historyEscortList) {
            if (userRunEscortData.isInsertOption()) {
                new CrossBiaoJuUserRunEscortImpl().add(userRunEscortData);
            } else if (userRunEscortData.isUpdateOption()) {
                new CrossBiaoJuUserRunEscortImpl().update(userRunEscortData);
            }
        }
    }

    public synchronized void addUnionExp(long expAdd) {
        userData.setUnionExpAdd(userData.getUnionExpAdd() + expAdd);
        userData.setDayUnionExpAdd(userData.getDayUnionExpAdd() + expAdd);
        userData.setLastBuildTime(DateHelper.getCurrentTime());
    }

    public synchronized CrossBiaoJuUserRunEscortData findEscortData(int escortUniqueId) {
        if (runEscortData!=null && runEscortData.getUniqueId() == escortUniqueId) {
            return runEscortData;
        }

        for (CrossBiaoJuUserRunEscortData escortData : historyEscortList) {
            if (escortData.getUniqueId() == escortUniqueId) {
                return escortData;
            }
        }

        return null;
    }

    public synchronized CrossBiaoJuUserRunEscortData findBestEscortData(int bestEscortUniqueId) {
        if (runEscortData != null && runEscortData.getBestEscortId() == bestEscortUniqueId) {
            return runEscortData;
        }

        for (CrossBiaoJuUserRunEscortData escortData : historyEscortList) {
            if (escortData.getBestEscortId() == bestEscortUniqueId) {
                return escortData;
            }
        }

        return null;
    }

    public synchronized int targetCanJoin(long targetUserId, int joinLimit) {
        if (runEscortData == null) {
            return GameErrorCode.E_BIAOJU_ESCORT_NOT_FOUND;
        }
        if (runEscortData.getUserId() == targetUserId) {
            return GameErrorCode.E_BIAOJU_ESCORT_JOINED;
        }
        if (!runEscortData.getBattleLogList().isEmpty()) {
            return GameErrorCode.E_BIAOJU_RUNNING_ESCORT;
        }

        if (runEscortData.getTeamUserList().size() >= joinLimit) {
            return GameErrorCode.E_BIAOJU_TEAM_JOIN_NUM_LIMIT;
        }

        if (runEscortData.getTeamUserList().stream().anyMatch(biaoJuTeamUserInfo -> biaoJuTeamUserInfo.getUserId() == targetUserId)) {
            return GameErrorCode.E_BIAOJU_ESCORT_JOINED;
        }

        return 0;
    }

    public synchronized int addTeamUser(long userId, int level, int joinLimit) {
        int ret = targetCanJoin(userId, joinLimit);
        if (ret != 0) {
            return ret;
        }
        runEscortData.addTeamUser(userId, level);

        return 0;
    }

    public synchronized int removeTeamUser(long userId) {
        if (runEscortData == null) {
            return GameErrorCode.E_BIAOJU_ESCORT_NOT_FOUND;
        }
        if (runEscortData.getRunStartTime() > 0) {
            return GameErrorCode.E_BIAOJU_RUNNING_ESCORT;
        }
        if (runEscortData.getTeamUserList().stream().noneMatch(e -> e.getUserId() == userId)) {
            return GameErrorCode.E_BIAOJU_ESCORT_NOT_JOINED;
        }

        runEscortData.removeTeamUser(userId);

        return 0;
    }
}
